package com.google.code.coma.gui.dialog;

import com.google.code.coma.Coma;
import com.google.code.coma.domain.Order;
import com.google.code.coma.gui.worker.WorkerManager;
import com.google.code.coma.rmi.RMIManager;
import com.google.code.coma.space.util.SpaceManager;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.layout.GridPane;
import javafx.stage.Modality;
import javafx.stage.Stage;
import javafx.stage.StageStyle;
import org.mozartspaces.core.*;

import java.net.URI;
import java.rmi.RemoteException;

/**
 * @author Dominik Strasser, dominikstr@gmail.com
 */
public class CreateOrderDialog extends Stage {
	private int amount;

	private String cpuType = cpuTypes[0];

	private int ramAmount;

	private boolean graphicsCard;

	private static final String[] cpuTypes = {"1_6_Single_Core", "2_0_Dual_Core", "2_4_Quad_Core"};

	private String factoryId;

	public CreateOrderDialog(final WorkerManager.Mode operationMode, String factoryId) {
		super();
		this.factoryId = factoryId;
		initModality(Modality.APPLICATION_MODAL);
		initStyle(StageStyle.UTILITY);
		setTitle("Create Order");
		setWidth(250);
		setHeight(180);

		GridPane grid = new GridPane();
		grid.setPadding(new Insets(10, 10, 10, 10));
		grid.setVgap(5);
		grid.setHgap(5);
		grid.setStyle("-fx-background-color: DAE6F3");

		final Button okButton = new Button("Create");
		okButton.setOnAction(new EventHandler<ActionEvent>() {
			@Override
			public void handle(ActionEvent actionEvent) {
				if (amount < 1) return;
				if (ramAmount < 1) return;
				if (cpuType == null) return;
				Order order = new Order(amount, cpuType, ramAmount, graphicsCard);
				if (operationMode == WorkerManager.Mode.SPACE) {
					spaceSaveOrder(order);
					afterSave();
				} else if (operationMode == WorkerManager.Mode.RMI) {
					rmiSaveOrder(order);
					afterSave();
				} else {
					System.err.println("Uups. invalid operation mode");
				}
			}
		});

		//size of order
		Label amountLabel = new Label("Amount: ");
		GridPane.setConstraints(amountLabel, 0, 0);
		grid.getChildren().add(amountLabel);
		final TextField amountField = new TextField("" + amount);
		amountField.textProperty().addListener(new ChangeListener<String>() {
			@Override
			public void changed(ObservableValue<? extends String> observableValue, String oldValue, String newValue) {
				try {
					amount = Integer.parseInt(newValue);
				} catch (Exception e) {
					amount = 0;
				}
			}
		});
		GridPane.setConstraints(amountField, 1, 0);
		grid.getChildren().add(amountField);

		//cpu type
		Label typeLabel = new Label("CPU Type: ");
		GridPane.setConstraints(typeLabel, 0, 1);
		grid.getChildren().add(typeLabel);
		ChoiceBox typeCB = new ChoiceBox<String>(FXCollections.observableArrayList(cpuTypes));
		typeCB.getSelectionModel().select(0);
		typeCB.getSelectionModel().selectedItemProperty().addListener(new ChangeListener<String>() {
			@Override
			public void changed(ObservableValue<? extends String> observableValue, String oldValue, String newValue) {
				CreateOrderDialog.this.cpuType = newValue;
			}
		});
		GridPane.setConstraints(typeCB, 1, 1);
		grid.getChildren().add(typeCB);

		//ram modules
		Label ramAmountLabel = new Label("RAM Modules: ");
		GridPane.setConstraints(ramAmountLabel, 0, 2);
		grid.getChildren().add(ramAmountLabel);
		final TextField ramAmountField = new TextField("" + ramAmount);
		ramAmountField.textProperty().addListener(new ChangeListener<String>() {
			@Override
			public void changed(ObservableValue<? extends String> observableValue, String oldValue, String newValue) {
				try {
					ramAmount = Integer.parseInt(newValue);
				} catch (Exception e) {
					ramAmount = 0;
				}
			}
		});
		GridPane.setConstraints(ramAmountField, 1, 2);
		grid.getChildren().add(ramAmountField);

		//graphicscard
		Label graphicsLabel = new Label("Graphicscard: ");
		GridPane.setConstraints(graphicsLabel, 0, 3);
		grid.getChildren().add(graphicsLabel);
		CheckBox checkBox = new CheckBox();
		checkBox.selectedProperty().addListener(new ChangeListener<Boolean>() {
			@Override
			public void changed(ObservableValue<? extends Boolean> observableValue, Boolean oldValue, Boolean newValue) {
				CreateOrderDialog.this.graphicsCard = newValue;
			}
		});
		GridPane.setConstraints(checkBox, 1, 3);
		grid.getChildren().add(checkBox);

		GridPane.setConstraints(okButton, 1, 4);
		grid.getChildren().add(okButton);

		Scene scene = new Scene(grid);
		setScene(scene);
	}

	private void spaceSaveOrder(Order order) {
		MzsCore core = DefaultMzsCore.newInstance(0);
		Capi capi = new Capi(core);
		try {
			ContainerReference containerReference = SpaceManager.getOrCreateNamedContainer(URI.create("xvsm://localhost:4242"), factoryId + "_" + Coma.ORDER_CONTAINER, capi);
			capi.write(new Entry(order), containerReference);
		} catch (MzsCoreException e) {
			core.shutdown(false);
			throw new RuntimeException("Unable to get container", e);
		}
	}

	private void rmiSaveOrder(Order order) {
		try {
			RMIManager.getStorageService(factoryId+"_"+Coma.ORDER_CONTAINER).add(order);
		} catch (RemoteException e) {
			throw new RuntimeException("Unable to save order",e);
		}

	}

	private void afterSave() {
		close();
	}
}
